package com.bjy.qa.agent.transport.websocket;

import com.alibaba.fastjson.JSONObject;
import com.bjy.qa.agent.context.Context;
import com.bjy.qa.agent.exception.MyException;
import com.bjy.qa.agent.model.KeyValueStore;
import com.bjy.qa.agent.tester.LogUtil;
import okhttp3.Response;
import okio.ByteString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

/**
 * 标准 WebSocket 服务接口
 */
public class WebSocketService implements IWebSocketService {
    private static final Logger logger = LoggerFactory.getLogger(WebSocketService.class);

    private WebSocketHelper webSocketHelper;

    private boolean opened = false; // WebSocket 链接是否已经打开

    private List<SendThread> sendThreadList = new ArrayList<SendThread>(); // 发送线程列表

    /**
     * 构造函数
     * @param endingType 结束符类型
     * @param url url
     * @param urlParams url 参数
     * @throws UnsupportedEncodingException
     * @throws InterruptedException
     */
    public WebSocketService(Context context, LogUtil logUtil, EndingType endingType, String url, List<KeyValueStore> urlParams) throws UnsupportedEncodingException, InterruptedException {
        if (webSocketHelper == null) {
            openWebSocket(endingType, url, urlParams);
        }
    }

    @Override
    public void send(String sendText, long interval, String assertStr, String setStr, boolean lose, JSONObject options) {
        if (interval == 0) { // 发送间隔为 0，直接发送一次
            sending(sendText);
        } else { // 发送间隔不为 0，启动发送线程，定时重复发送
            SendThread sendThread = new SendThread(interval, sendText);
            sendThreadList.add(sendThread);
            sendThread.start();
        }
    }

    @Override
    public void receive(String sendText, long interval, String assertStr, String setStr, boolean lose, JSONObject options) {

    }

    /**
     * 关闭连接
     */
    @Override
    public void close(String msg) {
        // 循环关闭所有发送线程
        for (SendThread sendThread : sendThreadList) {
            sendThread.interrupt();
        }
        webSocketHelper.close(msg); // 关闭 websocket 连接
        webSocketHelper = null;
    }

    @Override
    public boolean hasPending() {
        return false;
    }

    @Override
    public String getPendingMessages() {
        return null;
    }

    /**
     * 打开 websocket 连接
     * @param endingType 结束符类型
     * @param url url
     * @param urlParams url 参数
     * @throws InterruptedException
     * @throws UnsupportedEncodingException
     */
    private void openWebSocket(EndingType endingType, String url, List<KeyValueStore> urlParams) throws InterruptedException, UnsupportedEncodingException {
        webSocketHelper = new WebSocketHelper().getInstance(endingType, url, urlParams, new WebSocketHelper.WebSocketListener() {
            @Override
            public void onOpen(WebSocketHelper webSocketHelper, Response response) {
                opened = true;
            }

            @Override
            public void onMessage(WebSocketHelper webSocketHelper, String text) {
                System.out.println(text);
            }

            @Override
            public void onMessage(WebSocketHelper webSocketHelper, ByteString bytes) {
                System.out.println("onMessage");
            }

            @Override
            public void onClosing(WebSocketHelper webSocketHelper, int code, String reason) {
                opened = false;
            }

            @Override
            public void onClosed(WebSocketHelper webSocketHelper, int code, String reason) {
                opened = false;
            }

            @Override
            public void onFailure(WebSocketHelper webSocketHelper, Throwable throwable, Response response) {
                throwable.printStackTrace();
                logger.error("onFailure。Throwable : " + throwable + "。 Response: " + response);
            }
        });
    }

    /**
     * 发送消息
     * @param text 消息内容
     */
    private void sending(String text) {
        long timeOut = System.currentTimeMillis() + webSocketHelper.getTimeout() * 1000;
        while (true) {
            if (this.opened) {
                if (webSocketHelper.send(text)) {
                    return;
                } else {
                    throw new MyException("Websocket send failed, text: " + text);
                }
            }

            if (System.currentTimeMillis() >= timeOut) {
                throw new MyException("Websocket send timeout, text: " + text);
            }

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
        }
    }

    /**
     * 发送线程（需要定时发送时需要）
     */
    class SendThread extends Thread {
        long interval = 0; // 间隔发送时间
        String sendMsg;

        /**
         * 构造函数
         * @param interval 间隔发送时间
         * @param sendMsg 发送消息
         */
        public SendThread(long interval, String sendMsg) {
            this.interval = interval;
            this.sendMsg = sendMsg;
        }

        @Override
        public void run() {
            while (true) {
                sending(sendMsg);

                try {
                    sleep(interval);
                } catch (InterruptedException e) {
                    return;
                }
            }
        }
    }
}